
// Classe para recuperar estado do Tetragnatha apos quebra.

#include <iostream>
#include <cstdio>  // para abrir arquivo
#include <string>
#include <map>
#include <fstream>
#include <ctime>

#include "TetraRecovery.h"
#include "../classes_net/URL.h"
#include "../classes_net/URLFileDealer.h"
#include "../classes_dados/Hasher.h"
#include "../classes_dados/ManagerBerthier.h"
#include "../classes_dados/ThreadFunctionDatabase.h"
#include "../classes_dados/Repository.h"


#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/tr1/memory.hpp>


using namespace std;


TetraRecovery::TetraRecovery(){
	
//	pDisk[0] = fopen64 ("DiscoURL_P0.bin","ab+");  //Leitura e "escrita no final"
//	pDisk[1] = fopen64 ("DiscoURL_P1.bin","ab+");  //Leitura e "escrita no final"
//	pDisk[2] = fopen64 ("DiscoURL_P2.bin","ab+");  //Leitura e "escrita no final"
//	pDisk[3] = fopen64 ("DiscoURL_P3.bin","ab+");  //Leitura e "escrita no final"
//	pDisk[4] = fopen64 ("DiscoURL_P4.bin","ab+");  //Leitura e "escrita no final"
//	pDisk[5] = fopen64 ("DiscoURL_P5.bin","ab+");  //Leitura e "escrita no final"
//	
//	for(int i=0; i<6; i++)
//	    if (pDisk[i] == NULL){
//	    	cout << "Erro ao abrir o arquivo de disco pDisk: "<< i << endl;
//	    	exit(1);
//	    }
//	
//    pSaveDiskReadPos[0] = fopen64 ("pSaveDiskReadPos_P0","r+");  //Leitura e escreve
//    pSaveDiskReadPos[1] = fopen64 ("pSaveDiskReadPos_P1","r+");  //Leitura e escreve
//    pSaveDiskReadPos[2] = fopen64 ("pSaveDiskReadPos_P2","r+");  //Leitura e escreve
//    pSaveDiskReadPos[3] = fopen64 ("pSaveDiskReadPos_P3","r+");  //Leitura e escreve
//    pSaveDiskReadPos[4] = fopen64 ("pSaveDiskReadPos_P4","r+");  //Leitura e escreve
//    pSaveDiskReadPos[5] = fopen64 ("pSaveDiskReadPos_P5","r+");  //Leitura e escreve
//    
//    for(int i=0; i<6; i++)
//	    if (pSaveDiskReadPos[i] == NULL){
//	    	cout << "Erro ao abrir o arquivo de disco pSaveDiskReadPos: " << i << endl;
//	    	exit(1);
//	    }
//    
//    URLBuffer_IN = new _t_URL;
//    URLBuffer_OUT = new _t_URL;	
}


TetraRecovery::~TetraRecovery(){
//	for(int i=0; i<6; i++)	 
//		if(pDisk[i] != NULL) fclose (pDisk[i]);
//	
//	for(int i=0; i<6; i++)
//		if(pSaveDiskReadPos[i] != NULL) fclose (pSaveDiskReadPos[i]);
//	
//	delete URLBuffer_IN;
//	delete URLBuffer_OUT;
}


//long long TetraRecovery::size(int id){
//	long long pDiskSize;
//	if(id < 0) id = 0;
//	if(id > 5) id = 5;
//  	fseeko64 (pDisk[id] , 0 , SEEK_END); //vai para o final
//  	pDiskSize = ftello64 (pDisk[id]);  	// Pega o tamanho
//  	pDiskSize = pDiskSize / sizeof(_t_URL);
//  	return pDiskSize;
//}
//
//
//long long TetraRecovery::pos(int id){
//	long long _save_pos;
//	if(id < 0) id = 0;
//	if(id > 5) id = 5;
//  	rewind (pSaveDiskReadPos[id]);
//  	fscanf (pSaveDiskReadPos[id], "%lld", &_save_pos);
//  	return _save_pos;
//}



void TetraRecovery::recovery(void){
	//estrutura para Hash de URLs visitadas
	std::tr1::shared_ptr<URLFileDealer> urlFileDealer = URLFileDealer::getInstance();
//	unsigned long long t_hash;
	string t_hash;
	ifstream in_Hash_File("readURLHashes");

	//Recupera Hash dos arquivos do disco
	while(!in_Hash_File.eof()){
		in_Hash_File >> t_hash;
		urlFileDealer->initURLHashSet(t_hash);
	}
		
	in_Hash_File.close();
	
	//recupera NumPaginas
	uint numPaginasRec;
	ifstream numPaginasBackUp("./out_logger/contadorPaginas");
	while(!numPaginasBackUp.eof()) numPaginasBackUp >> numPaginasRec;
//	ThreadFunctionDatabase::setNumPaginas(numPaginasRec);
	Repository::setContador(numPaginasRec);
}



//
//void TetraRecovery::contaPaginasDisco(void){
//	long long save_pos_disk;
//	long long disk_size;
//	URL tempUrl;
//	int id = 0;
//	unsigned long long urlHash;
//	
//	long long singleURLs = 0;
//	
//	cout << "Modo especial:  Contando links do Disco " << endl;
//	// Ensinando o Tetragnatha a contar...
//	for(id = 0; id < 6; id++){
//		save_pos_disk = pos(id);
//		disk_size = size(id);
//		cout << "Disco " << id << " -> Total Lido: " << save_pos_disk-1 << " URLs" << endl;
//		cout << "Tamanho do Disco: " << disk_size << " URLs" << endl;
//		for(long long posd=0; posd < save_pos_disk; posd++){
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	    tempUrl = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
//
//	  	    urlHash = Hasher::hash64FromString(tempUrl.toString());
//	  	    
//			if  (urlHashMapRecovery[urlHash] == false){ //verifica se tem 
//				urlHashMapRecovery[urlHash] = true;     //marca que agora tem
//				singleURLs++;
//			}	
//		}	
//		cout << "---> Total nao repetido: " << singleURLs << endl;
//		singleURLs = 0;
//	}
//	urlHashMapRecovery.clear(); //limpa tudo do map
//	
//	for(id = 0; id < 6; id++){
//		save_pos_disk = pos(id);
//		disk_size = size(id);
//		cout << "Disco :" << id << endl;
//		for(long long posd=save_pos_disk; posd < disk_size; posd++){
//			
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	  	
//	  	    tempUrl = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
//	
//	  	    urlHash = Hasher::hash64FromString(tempUrl.toString());
//	  	    		
//			if  (urlHashMapRecovery[urlHash] == false){ //verifica se tem 
//				urlHashMapRecovery[urlHash] = true;     //marca que agora tem
//				singleURLs++;
//			}	
//		}	
//		cout << "---> Total nao repetido ainda nao lido: " << singleURLs << endl;
//		singleURLs = 0;
//	}	
//	cout << "->>>   FIM !!!  " << endl;	
//}


//
//
//void TetraRecovery::createHashFile(void) {
//
//	long long save_pos_disk;
//	long long disk_size;
//	URL tempUrl;
//	int id = 0;
//	unsigned long long urlHash;
//	long long save_pos_temp;
//	
//	
//	ofstream readURLHashes("readURLHashes.TEMP");
//	
//	FILE * pDisk_TEMP[6];
//	
//	pDisk_TEMP[0] = fopen64 ("DiscoURL_P0_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[1] = fopen64 ("DiscoURL_P1_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[2] = fopen64 ("DiscoURL_P2_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[3] = fopen64 ("DiscoURL_P3_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[4] = fopen64 ("DiscoURL_P4_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[5] = fopen64 ("DiscoURL_P5_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	
//	for(int i=0; i<6; i++)
//	    if (pDisk_TEMP[i] == NULL){
//	    	cout << "Erro ao abrir o arquivo de disco pDisk_TEMP: "<< i << endl;
//	    	exit(1);
//	    }
//	
//
//	for(id = 0; id < 6; id++){
//		
//		save_pos_disk = pos(id);
//		disk_size = size(id);
//		save_pos_temp = 0;
//		
//		cout << "Disco " << id << " -> Total Lido: " << save_pos_disk-1 << " URLs" << endl;
//		cout << "Tamanho do Disco: " << disk_size << " URLs" << endl;
//		cout << "Passo 1:  Copiando antes ate a ultima pos lida ... " << endl;
//		
//		for(long long posd=0; posd < save_pos_disk; posd++){
//			
//			//Indica Passo
//			if( (posd%300000) == 1) cout << "[" << id << "] --> " << posd << " de " << save_pos_disk -1 << " concluido... " << endl;
//			
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	  	//Transforma em URL
//	  	    tempUrl = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
//	  	  
//	  	    urlHash = Hasher::hash64FromString(tempUrl.toString());  	    
//			readURLHashes << urlHash << endl; //Grava hash no arquivo
//
//		}	
//	}
//	
//	
//	for(int i=0; i<6; i++) fclose(pDisk_TEMP[i]);
//	readURLHashes.close();
//	
//	cout << "->>>   FIM !!!  " << endl;	
//}
//
//
//void TetraRecovery::cleanDisk(void){
//	
//	long long save_pos_disk;
//	long long disk_size;
//	URL tempUrl;
//	int id = 0;
//	int res;
//	unsigned long long urlHash;
//	long long save_pos_temp;
//	
//	
//	ofstream temp_savePos("temp_savePos");
//	FILE * pDisk_TEMP[6];
//	
//	pDisk_TEMP[0] = fopen64 ("DiscoURL_P0_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[1] = fopen64 ("DiscoURL_P1_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[2] = fopen64 ("DiscoURL_P2_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[3] = fopen64 ("DiscoURL_P3_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[4] = fopen64 ("DiscoURL_P4_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	pDisk_TEMP[5] = fopen64 ("DiscoURL_P5_TEMP.bin","ab+");  //Leitura e "escrita no final"
//	
//	for(int i=0; i<6; i++)
//	    if (pDisk_TEMP[i] == NULL){
//	    	cout << "Erro ao abrir o arquivo de disco pDisk_TEMP: "<< i << endl;
//	    	exit(1);
//	    }
//	
//	cout << "Modo especial:  Limpando Disco " << endl;
//	
//	for(id = 0; id < 6; id++){
//		
//		save_pos_disk = pos(id);
//		disk_size = size(id);
//		save_pos_temp = 0;
//		
//		cout << "Disco " << id << " -> Total Lido: " << save_pos_disk-1 << " URLs" << endl;
//		cout << "Tamanho do Disco: " << disk_size << " URLs" << endl;
//		cout << "Passo 1:  Copiando antes ate a ultima pos lida ... " << endl;
//		
//		for(long long posd=0; posd < save_pos_disk; posd++){
//			
//			//Indica Passo
//			if( (posd%300000) == 1) cout << "[" << id << "] --> " << posd << " de " << save_pos_disk -1 << " concluido... " << endl;
//			
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	  	//Transforma em URL
//	  	    tempUrl = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
//	  	    
//	  	    urlHash = Hasher::hash64FromString(tempUrl.toString());  	    
//	  	    if  (urlHashMapRecovery[urlHash] == false){ //verifica se tem 
//				urlHashMapRecovery[urlHash] = true;     //marca que agora tem
//				res = fwrite(URLBuffer_IN, sizeof(_t_URL), 1, pDisk_TEMP[id] );
//				if(res != 1) cout << "Erro ao gravar em URLDiskClass::writeDisk() " <<  endl;
//				save_pos_temp++; //incrementa 
//			}	
//		}	
//		
//		temp_savePos << save_pos_temp << endl;
//		
//		cout << "Passo 2:  Copiando da ultima pos lida ate o final ... " << endl;		
//		for(long long posd=save_pos_disk; posd < disk_size; posd++){
//			
//			//Indica passo
//			if( (posd%300000) == 1) cout << "[" << id << "] --> " << posd << " de " << disk_size << " concluido... " << endl;
//			//Le do disco
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	  	//Escreve no disco
//			res = fwrite(URLBuffer_IN, sizeof(_t_URL), 1, pDisk_TEMP[id] );
//			if(res != 1) cout << "Erro ao gravar em URLDiskClass::writeDisk() " <<  endl;
//		
//		}	
//	}
//	
//	cout << "->>>   FIM !!!  " << endl;	
//}



//
//void TetraRecovery::currentState(int _now){
//	long long save_pos_disk;
//	URL tempUrl;
//	int id = 0;
////	string urlHash = "";
//	unsigned long long urlHash;
//	
//	long long singleURLs = 0;
//	time_t tempo;
//	time(&tempo);
//
//	cout << tempo;
//	cout << " " << tempo - _now;
//	for(id = 0; id < 6; id++){
//		save_pos_disk = pos(id);
//		for(long long posd=0; posd < save_pos_disk; posd++){
//	  	  	fseeko64 ( pDisk[id], posd*sizeof(_t_URL) , SEEK_SET);
//	  	  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[id]);
//	  	    tempUrl = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
//	  	    
//	  	    urlHash = Hasher::hash64FromString(tempUrl.toString());
//	  	  
//			if  (urlHashMapRecovery[urlHash] == false){ //verifica se tem 
//				urlHashMapRecovery[urlHash] = true;     //marca que agora tem
//				singleURLs++;
//			}	
//		}	
//		cout << " " << singleURLs;
//		singleURLs = 0;
//	}
//	cout << endl;
//	urlHashMapRecovery.clear(); //limpa tudo do map
//}




	
	